package com.allm.ai.api.interceptor;

import java.io.IOException;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import com.allm.ai.api.context.UserContextHolder;
import com.allm.ai.api.dto.UserInfo;
import com.allm.ai.api.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.authing.sdk.java.client.AuthenticationClient;
import cn.authing.sdk.java.dto.ValidateTokenRespDto;
import cn.authing.sdk.java.dto.authentication.ValidateTokenParams;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    private final AuthenticationClient authClient;
    private final UserService userService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public AuthInterceptor(AuthenticationClient authClient, UserService userService) {
        this.authClient = authClient;
        this.userService = userService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 跳过 OPTIONS 请求
        if ("OPTIONS".equals(request.getMethod())) {
            return true;
        }

        // 1. 获取请求路径
        String requestPath = request.getRequestURI();
        log.debug("AuthInterceptor: processing request for path '{}'", requestPath);

        // 2. 获取 Authorization 头
        String authHeader = request.getHeader("Authorization");
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            log.warn("缺少有效的 Authorization 头: {}", requestPath);
            sendErrorResponse(response, "缺少认证令牌");
            return false;
        }
        String token = authHeader.substring(7); // 移除 "Bearer " 前缀

        // 3. 验证 Authing Access Token
        ValidateTokenRespDto validateTokenRespDto = null;
        try {
            validateTokenRespDto = verifyAuthingToken(token);
            if (validateTokenRespDto == null) {
                log.warn("Token 验证失败: {}", requestPath);
                sendErrorResponse(response, "认证令牌无效");
                return false;
            }
            log.debug("用户认证成功: userId={}, path={}", validateTokenRespDto.getSub(), requestPath);
        } catch (Exception e) {
            log.error("Token 验证异常: {}, path={}", e.getMessage(), requestPath, e);
            sendErrorResponse(response, "认证失败");
            return false;
        }

        // 4. 获取用户信息
        UserInfo userInfo = getUserInfo(validateTokenRespDto);
        if (userInfo == null) {
            log.warn("用户信息获取失败: {}", requestPath);
            sendErrorResponse(response, "用户信息获取失败");
            return false;
        }

        // 5. 【核心步骤】将用户信息存入UserContextHolder，线程上下文缓存
        UserContextHolder.setUser(userInfo);

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 请求处理完毕后，清理线程本地变量，防止内存泄漏
        UserContextHolder.clear();
    }

    /**
     * 验证 Authing JWT Token - 使用 AuthenticationClient
     */
    private ValidateTokenRespDto verifyAuthingToken(String idToken) {
        try {
            ValidateTokenParams params = new ValidateTokenParams();
            params.setIdToken(idToken);
            ValidateTokenRespDto loginStatus = authClient.validateToken(params);
            
            // 检查令牌是否有效且未过期
            if (loginStatus != null && loginStatus.getExp() * 1000 > System.currentTimeMillis()) {
                log.debug("Token validation successful for user: {}", loginStatus.getSub());
                return loginStatus;
            }
            log.warn("Token is invalid or expired.");
            return null;

        } catch (Exception e) {
            log.error("Token validation or user fetching failed with exception: {}", e.getMessage(), e);
            return null;
        }
    }

    private UserInfo getUserInfo(ValidateTokenRespDto validateTokenRespDto) {
        String userId = validateTokenRespDto.getSub();
        // 获取用户信息（带缓存）
        UserInfo userInfo = userService.getUserInfoWithCache(userId);
        if (userInfo != null) {
            return userInfo;
        }
        return null;
    }

    /**
     * 发送未授权响应
     */
    private void sendErrorResponse(HttpServletResponse response, String message) throws IOException {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType("application/json;charset=UTF-8");

        Map<String, Object> result = Map.of(
                "success", false,
                "code", 401,
                "message", message,
                "timestamp", System.currentTimeMillis()
        );
        response.getWriter().write(objectMapper.writeValueAsString(result));
    }
}